home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / mac / raytrace / dkb / mcprt102.bnh / DKBTrace-Mac / trace.c < prev   
Encoding:
C/C++ Source or Header  |  1991-07-05  |  18.1 KB  |  652 lines

  1. /*****************************************************************************
  2. *
  3. *                                     trace.c
  4. *
  5. *   from DKBTrace (c) 1990  David Buck
  6. *
  7. *  This module contains the entry routine for the raytracer and the code to
  8. *  parse the parameters on the command line.
  9. *
  10. *
  11. * This software is freely distributable. The source and/or object code may be
  12. * copied or uploaded to communications services so long as this notice remains
  13. * at the top of each file.  If any changes are made to the program, you must
  14. * clearly indicate in the documentation and in the programs startup message
  15. * who it was who made the changes. The documentation should also describe what
  16. * those changes were. This software may not be included in whole or in
  17. * part into any commercial package without the express written consent of the
  18. * author.  It may, however, be included in other public domain or freely
  19. * distributed software so long as the proper credit for the software is given.
  20. *
  21. * This software is provided as is without any guarantees or warranty. Although
  22. * the author has attempted to find and correct any bugs in the software, he
  23. * is not responsible for any damage caused by the use of the software.  The
  24. * author is under no obligation to provide service, corrections, or upgrades
  25. * to this package.
  26. *
  27. * Despite all the legal stuff above, if you do find bugs, I would like to hear
  28. * about them.  Also, if you have any comments or questions, you may contact me
  29. * at the following address:
  30. *
  31. *     David Buck
  32. *     22C Sonnet Cres.
  33. *     Nepean Ontario
  34. *     Canada, K2H 8W7
  35. *
  36. *  I can also be reached on the following bulleton boards:
  37. *
  38. *     OMX              (613) 731-3419
  39. *     Mystic           (613) 596-4249  or  (613) 596-4772
  40. *
  41. *  Fidonet:   1:163/109.9
  42. *  Internet:  dbuck@ccs.carleton.ca
  43. *  The "You Can Call Me RAY" BBS    (708) 358-5611
  44. *
  45. *  IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
  46. *
  47. *     The "You Can Call Me RAY" BBS (708) 358-5611
  48. *     The Information Exchange BBS  (708) 945-5575
  49. *
  50. *****************************************************************************/
  51.  
  52. #include <ctype.h>
  53. #include "frame.h"        /* common to ALL modules in this program */
  54. #include "dkbproto.h"
  55.  
  56. #define MAX_FILE_NAMES 1
  57. unsigned int Options;
  58. int Quality;
  59.  
  60. FILE *bfp;
  61.  
  62. extern FRAME Frame;
  63.  
  64. char Input_File_Name[FILE_NAME_LENGTH], Output_File_Name[FILE_NAME_LENGTH];
  65.  
  66. #define MAX_LIBRARIES 10
  67. char *Library_Paths[MAX_LIBRARIES];
  68. int Library_Path_Index;
  69.  
  70. FILE_HANDLE *Output_File_Handle;
  71. int File_Buffer_Size;
  72. static int Number_Of_Files;
  73. DBL VTemp;
  74. DBL Antialias_Threshold;
  75. int First_Line, Last_Line;
  76. int Display_Started = FALSE;
  77.  
  78. /* Stats kept by the ray tracer: */
  79. long Number_Of_Pixels, Number_Of_Rays, Number_Of_Pixels_Supersampled;
  80. long Ray_Sphere_Tests, Ray_Sphere_Tests_Succeeded;
  81. long Ray_Plane_Tests, Ray_Plane_Tests_Succeeded;
  82. long Ray_Triangle_Tests, Ray_Triangle_Tests_Succeeded;
  83. long Ray_Quadric_Tests, Ray_Quadric_Tests_Succeeded;
  84. long Ray_Quartic_Tests, Ray_Quartic_Tests_Succeeded;
  85. long Bounding_Region_Tests, Bounding_Region_Tests_Succeeded;
  86. long Calls_To_Noise, Calls_To_DNoise;
  87. long Shadow_Ray_Tests, Shadow_Rays_Succeeded;
  88. long Reflected_Rays_Traced, Refracted_Rays_Traced;
  89. long Transmitted_Rays_Traced;
  90.  
  91. char DisplayFormat, OutputFormat;
  92.  
  93. void Main (argc, argv)
  94.   int argc;
  95.   char **argv;
  96.   {
  97.   register int i;
  98.  
  99.   STARTUP_DKB_TRACE
  100.  
  101.   printf ("\n\n          DKB Ray Trace   Version 2.12\n");
  102.   printf ("          ----------------------------\n\n");
  103.   printf ("        Copyright (c) 1991  David K. Buck\n\n");
  104.   printf ("  Written by:\n");
  105.   printf ("  David K. Buck (dbuck@ccs.carleton.ca) (CIS: 70521, 1371)\n");
  106.   printf ("  22C Sonnet Cr.  Nepean, Ontario\n");
  107.   printf ("  Canada, K2H 8W7\n\n");
  108.   printf ("  This program is freely distributable.\n\n");
  109.  
  110.   printf ("  Conversion to IBM P.C. w/TARGA output and\n");
  111.   printf ("  other various improvements by Aaron A. Collins\n\n");
  112.  
  113.   printf ("  GIF format file reader by Steve A. Bennett\n\n");
  114.  
  115.   printf ("  Noise and DNoise functions by Robert Skinner\n\n");
  116.  
  117.   printf ("  Quartic (4th order) Shapes by Alexander Enzmann\n\n");
  118.  
  119.   PRINT_OTHER_CREDITS
  120.  
  121. /* Parse the command line parameters */
  122.   if (argc == 1)
  123.      usage();
  124.  
  125.   init_vars();
  126.  
  127.   Output_File_Name[0]='\0';
  128.  
  129.   Library_Paths[0] = NULL;
  130.   Library_Path_Index = 0;
  131.  
  132. /* Read the default parameters from trace.def */
  133.   get_defaults();
  134.  
  135.   for (i = 1 ; i < argc ; i++ )
  136.     if ((*argv[i] == '+') || (*argv[i] == '-'))
  137.       parse_option(argv[i]);
  138.     else
  139.       parse_file_name(argv[i]);
  140.  
  141.    if (Last_Line == -1)
  142.       Last_Line = Frame.Screen_Height;
  143.  
  144.    if (Options & DISKWRITE) {
  145.       switch (OutputFormat) {
  146.          case '\0':
  147.          case 'd':
  148.          case 'D':
  149.                    if ((Output_File_Handle = Get_Dump_File_Handle()) == NULL) {
  150.                       close_all();
  151.                       exit(1);
  152.                       }
  153.                    break;
  154. /*
  155.          case 'i':
  156.          case 'I':
  157.                    if ((Output_File_Handle = Get_Iff_File_Handle()) == NULL) {
  158.                       close_all();
  159.                       exit(1);
  160.                       }
  161.                    break;
  162.  
  163. */
  164.          case 'r':
  165.          case 'R':
  166.                    if ((Output_File_Handle = Get_Raw_File_Handle()) == NULL) {
  167.                       close_all();
  168.                       exit(1);
  169.                       }
  170.                    break;
  171.  
  172.          case 't':
  173.          case 'T':
  174.                    if ((Output_File_Handle = Get_Targa_File_Handle()) == NULL) {
  175.                       close_all();
  176.                       exit(1);
  177.                       }
  178.                    break;
  179.  
  180.          default:
  181.                    fprintf (stderr, "Unrecognized output file format %c\n", OutputFormat);
  182.                    exit(1);
  183.          }
  184.  
  185.       if (Output_File_Name[0] == '\0')
  186.          strcpy (Output_File_Name, Default_File_Name (Output_File_Handle));
  187.       }
  188.  
  189.    Print_Options();
  190.  
  191.    Initialize_Tokenizer(Input_File_Name);
  192.    printf ("Parsing...\n");
  193.    Parse (&Frame);
  194.    Terminate_Tokenizer();
  195.  
  196.   if (Options & DISPLAY)
  197.     {
  198.     printf ("Displaying...\n");
  199.     display_init(Frame.Screen_Width, Frame.Screen_Height);
  200.     Display_Started = TRUE;
  201.     }
  202.  
  203. /* Get things ready for ray tracing */
  204.    if (Options & DISKWRITE)
  205.       if (Options & CONTINUE_TRACE) {
  206.          if (Open_File (Output_File_Handle, Output_File_Name,
  207.                  &Frame.Screen_Width, &Frame.Screen_Height, File_Buffer_Size,
  208.                  READ_MODE) != 1) {
  209.             fprintf (stderr, "Error opening output file\n");
  210.             close_all();
  211.             exit(1);
  212.             }
  213.  
  214.          initialize_renderer();
  215.          Read_Rendered_Part();
  216.          }
  217.       else {
  218.          if (Open_File (Output_File_Handle, Output_File_Name,
  219.                  &Frame.Screen_Width, &Frame.Screen_Height, File_Buffer_Size,
  220.                  WRITE_MODE) != 1) {
  221.             fprintf (stderr, "Error opening output file\n");
  222.             close_all();
  223.             exit(1);
  224.             }
  225.  
  226.          initialize_renderer();
  227.          }
  228.   else
  229.      initialize_renderer();
  230.  
  231.   pq_init();
  232.   Initialize_Noise();
  233.  
  234. /* Ok, go for it - trace the picture */
  235.   if (!(Options & DISPLAY))
  236.       printf ("Rendering...\n");
  237.   Start_Tracing ();
  238.  
  239. /* Wait for a CR if the user requested it. */
  240.  
  241. /* Clean up and leave */
  242.   display_finished();
  243.  
  244.   close_all ();
  245.   print_stats();
  246.  
  247.   FINISH_DKB_TRACE
  248.   }
  249.  
  250. /* Print out usage error message */
  251.  
  252. void usage ()
  253.     {
  254.     printf ("\nUsage:");
  255.     printf ("\n   trace  [+/-] Option1 [+/-] Option2");
  256.     printf ("\n");
  257.     printf ("\n Options:");
  258.     printf ("\n    dx = display in format x");
  259.     printf ("\n    v  = verbose");
  260.     printf ("\n    p  = prompt exit");
  261.     printf ("\n    x  = enable early exit by key hit");
  262.     printf ("\n    fx = write output file in format x");
  263.     printf ("\n         ft - Uncompressed Targa-24  fd - DKB/QRT Dump  fr - 3 Raw Files");
  264.     printf ("\n    a  = perform antialiasing");
  265.     printf ("\n    c  = continue aborted trace");
  266.     printf ("\n    qx = image quality 0=rough, 9=full");
  267.     printf ("\n    lxxx = library path prefix");
  268.     printf ("\n    wxxx = width of the screen");
  269.     printf ("\n    hxxx = height of the screen");
  270.     printf ("\n    sxxx = start at line number xxx");
  271.     printf ("\n    exxx = end at line number xxx");
  272.     printf ("\n    bxxx = Use xxx kilobytes for output file buffer space");
  273.     printf ("\n    ifilename = input file name");
  274.     printf ("\n    ofilename = output file name");
  275.     printf ("\n\n");
  276.     exit(1);
  277.     }
  278.  
  279. void init_vars()
  280.   {
  281.   Output_File_Handle = NULL;
  282.   File_Buffer_Size = 0;
  283.   Options = 0;
  284.   Quality = 9;
  285.   Number_Of_Files = 0;
  286.   First_Line = 0;
  287.   Last_Line = -1;
  288.  
  289.   Number_Of_Pixels = 0L;
  290.   Number_Of_Rays = 0L;
  291.   Number_Of_Pixels_Supersampled = 0L;
  292.   Ray_Sphere_Tests = 0L;
  293.   Ray_Sphere_Tests_Succeeded = 0L;
  294.   Ray_Plane_Tests = 0L;
  295.   Ray_Plane_Tests_Succeeded = 0L;
  296.   Ray_Triangle_Tests = 0L;
  297.   Ray_Triangle_Tests_Succeeded = 0L;
  298.   Ray_Quadric_Tests = 0L;
  299.   Ray_Quadric_Tests_Succeeded = 0L;
  300.   Ray_Quartic_Tests = 0L;
  301.   Ray_Quartic_Tests_Succeeded = 0L;
  302.   Bounding_Region_Tests = 0L;
  303.   Bounding_Region_Tests_Succeeded = 0L;
  304.   Calls_To_Noise = 0L;
  305.   Calls_To_DNoise = 0L;
  306.   Shadow_Ray_Tests = 0L;
  307.   Shadow_Rays_Succeeded = 0L;
  308.   Reflected_Rays_Traced = 0L;
  309.   Refracted_Rays_Traced = 0L;
  310.   Transmitted_Rays_Traced = 0L;
  311.  
  312.   Frame.Screen_Height = 100;
  313.   Frame.Screen_Width = 100;
  314.  
  315.   Antialias_Threshold = 0.3;
  316.   strcpy (Input_File_Name, "object.dat");
  317.   return;
  318.   }
  319.  
  320. /* Close all the stuff that has been opened. */
  321. void close_all ()
  322.    {
  323.    if ((Options & DISPLAY) && Display_Started)
  324.      display_close();
  325.  
  326.    if (Output_File_Handle)
  327.       Close_File (Output_File_Handle);
  328.    }
  329.  
  330. /* Read the default parameters from trace.def*/
  331. void get_defaults()
  332.   {
  333.   FILE *defaults_file;
  334.   char Option_String[256], *Option_String_Ptr;
  335.  
  336. #ifndef Macintosh
  337.   if ((defaults_file = fopen("trace.def", "r")) != NULL) {
  338.      while (fgets(Option_String, 256, defaults_file) != NULL)
  339.         read_options(Option_String);
  340.      fclose (defaults_file);
  341.      }
  342. #endif
  343.  
  344.   if ((Option_String_Ptr = getenv("DKBOPT")) != NULL)
  345.      read_options(Option_String_Ptr);
  346.   }
  347.  
  348. void read_options (Option_Line)
  349.   char *Option_Line;
  350.   {
  351.   register int c, String_Index, Option_Started;
  352.   short Option_Line_Index = 0;
  353.   char Option_String[80];
  354.  
  355.   String_Index = 0;
  356.   Option_Started = FALSE;
  357.   while ((c = Option_Line[Option_Line_Index++]) != '\0')
  358.     {
  359.     if (Option_Started)
  360.       if (isspace(c))
  361.         {
  362.         Option_String[String_Index] = '\0';
  363.         parse_option (Option_String);
  364.         Option_Started = FALSE;
  365.     String_Index = 0;
  366.         }
  367.      else
  368.        Option_String[String_Index++] = (char) c;
  369.  
  370.     else /* Option_Started */
  371.       if ((c == (int) '-') || (c == (int) '+'))
  372.         {
  373.         String_Index = 0;
  374.         Option_String[String_Index++] = (char) c;
  375.         Option_Started = TRUE;
  376.         }
  377.       else
  378.         if (!isspace(c))
  379.           {
  380.           fprintf (stderr, "\nBad default file format.  Offending char: (%c), val: %d.\n", (char) c, c);
  381.           exit (1);
  382.           }
  383.     }
  384.  
  385.   if (Option_Started)
  386.     {
  387.     Option_String[String_Index] = '\0';
  388.     parse_option (Option_String);
  389.     }
  390.   }
  391.  
  392. /* parse the command line parameters */
  393. void parse_option (Option_String)
  394.   char *Option_String;
  395.   {
  396.   register int Add_Option;
  397.   unsigned int Option_Number;
  398.   DBL threshold;
  399.  
  400.   if (*(Option_String++) == '-')
  401.     Add_Option = FALSE;
  402.   else
  403.     Add_Option = TRUE;
  404.  
  405.   switch (*Option_String)
  406.     {
  407.     case 'B':
  408.     case 'b':  sscanf (&Option_String[1], "%d", &File_Buffer_Size);
  409.                File_Buffer_Size *= 1024;
  410.                if (File_Buffer_Size < BUFSIZ)
  411.                   File_Buffer_Size = BUFSIZ;
  412.                Option_Number = 0;
  413.                break;
  414.  
  415.     case 'C':
  416.     case 'c':  Option_Number = CONTINUE_TRACE;
  417.                break;
  418.  
  419.     case 'D':
  420.     case 'd':  Option_Number = DISPLAY;
  421.                DisplayFormat = (char)toupper(Option_String[1]);
  422.                if (DisplayFormat == '\0')
  423.                   DisplayFormat = '0';
  424.                break;
  425.  
  426.     case 'V':
  427.     case 'v':  Option_Number = VERBOSE;
  428.                break;
  429.  
  430.     case 'W':
  431.     case 'w':  sscanf (&Option_String[1], "%d", &Frame.Screen_Width);
  432.            Option_Number = 0;
  433.                break;
  434.  
  435.     case 'H':
  436.     case 'h':  sscanf (&Option_String[1], "%d", &Frame.Screen_Height);
  437.            Option_Number = 0;
  438.                break;
  439.  
  440.     case 'F':
  441.     case 'f':  Option_Number = DISKWRITE;
  442.                if (isupper(Option_String[1]))
  443.                   OutputFormat = (char)tolower(Option_String[1]);
  444.                else
  445.                   OutputFormat = Option_String[1];
  446.  
  447.                /* Default the output format to raw. */
  448.                if (OutputFormat == '\0')
  449.                   OutputFormat = DEFAULT_OUTPUT_FORMAT;
  450.                break;
  451.  
  452.     case 'P':
  453.     case 'p':  Option_Number = PROMPTEXIT;
  454.                break;
  455.  
  456.     case 'I':
  457.     case 'i':  strncpy (Input_File_Name, &Option_String[1], FILE_NAME_LENGTH);
  458.            Option_Number = 0;
  459.                break;
  460.  
  461.     case 'O':
  462.     case 'o':  strncpy (Output_File_Name, &Option_String[1], FILE_NAME_LENGTH);
  463.            Option_Number = 0;
  464.                break;
  465.  
  466.     case 'A':
  467.     case 'a':  Option_Number = ANTIALIAS;
  468.                if (sscanf (&Option_String[1], DBL_FORMAT_STRING, &threshold) != EOF)
  469.                    Antialias_Threshold = threshold;
  470.                break;
  471.  
  472.     case 'X':
  473.     case 'x':  Option_Number = EXITENABLE;
  474.                break;
  475.  
  476.  
  477.     case 'L':
  478.     case 'l':  if (Library_Path_Index >= MAX_LIBRARIES) {
  479.                   fprintf (stderr, "Too many library directories specified\n");
  480.                   exit(1);
  481.                   }
  482.  
  483.                Library_Paths [Library_Path_Index] = malloc (strlen(Option_String));
  484.            if (Library_Paths [Library_Path_Index] == NULL) {
  485.           fprintf (stderr, "Cannot allocate memory for library pathname\n");
  486.           exit(1);
  487.           }
  488.                strcpy (Library_Paths [Library_Path_Index], &Option_String[1]);
  489.                Library_Path_Index++;
  490.            Option_Number = 0;
  491.                break;
  492.  
  493.     case 'S':
  494.     case 's':  sscanf (&Option_String[1], "%d", &First_Line);
  495.            Option_Number = 0;
  496.                break;
  497.  
  498.     case 'E':
  499.     case 'e':  sscanf (&Option_String[1], "%d", &Last_Line);
  500.            Option_Number = 0;
  501.                break;
  502.  
  503.     case 'Q':
  504.     case 'q':  sscanf (&Option_String[1], "%d", &Quality);
  505.            Option_Number = 0;
  506.                break;
  507.  
  508.                /* Turn on debugging print statements. */
  509.     case 'Z':
  510.     case 'z':  Option_Number = DEBUGGING;
  511.                break;
  512.  
  513.     default:   fprintf (stderr, "\nInvalid option: %s\n\n", --Option_String);
  514.            Option_Number = 0;
  515.     }
  516.  
  517.   if (Option_Number != 0)
  518.       if (Add_Option)
  519.            Options |= Option_Number;
  520.       else Options &= ~Option_Number;
  521.   }
  522.  
  523. void Print_Options()
  524.    {
  525.    int i;
  526.  
  527.    printf ("Options in effect: ");
  528.  
  529.    if (Options & CONTINUE_TRACE)
  530.       printf ("+c ");
  531.    else
  532.       printf ("-c ");
  533.  
  534.    if (Options & DISPLAY)
  535.       printf ("+d%c ", DisplayFormat);
  536.    else
  537.       printf ("-d ");
  538.  
  539.    if (Options & VERBOSE)
  540.       printf ("+v ");
  541.    else
  542.       printf ("-v ");
  543.  
  544.    if (Options & DISKWRITE)
  545.       printf ("+f%c ", OutputFormat);
  546.    else
  547.       printf ("-f ");
  548.  
  549.    if (Options & PROMPTEXIT)
  550.       printf ("+p ");
  551.    else
  552.       printf ("-p ");
  553.  
  554.    if (Options & EXITENABLE)
  555.       printf ("+x ");
  556.    else
  557.       printf ("-x ");
  558.  
  559.    if (Options & ANTIALIAS)
  560.       printf ("+a%f ", Antialias_Threshold);
  561.    else
  562.       printf ("-a ");
  563.  
  564.    if (Options & DEBUGGING)
  565.       printf ("+z ");
  566.  
  567.    if (File_Buffer_Size != 0)
  568.       printf ("-b%d ", File_Buffer_Size/1024);
  569.  
  570.    printf ("-q%d -w%d -h%d -s%d -e%d\n-i%s ",
  571.            Quality, Frame.Screen_Width, Frame.Screen_Height,
  572.            First_Line, Last_Line, Input_File_Name);
  573.  
  574.    if (Options & DISKWRITE)
  575.       printf ("-o%s ", Output_File_Name);
  576.  
  577.    for (i = 0 ; i < Library_Path_Index ; i++)
  578.       printf ("-l%s ", Library_Paths[i]);
  579.  
  580.    printf ("\n");
  581.    }
  582.  
  583. void parse_file_name (File_Name)
  584.   char *File_Name;
  585.   {
  586.   FILE *defaults_file;
  587.   char Option_String[256];
  588.  
  589.   if (++Number_Of_Files > MAX_FILE_NAMES)
  590.     {
  591.     fprintf (stderr, "\nOnly %d file names are allowed in a command line.", 
  592.              MAX_FILE_NAMES);
  593.     exit(1);
  594.     }
  595.  
  596.   if ((defaults_file = fopen(File_Name, "r")) != NULL) {
  597.      while (fgets(Option_String, 256, defaults_file) != NULL)
  598.         read_options(Option_String);
  599.      fclose (defaults_file);
  600.      }
  601.   }
  602.  
  603. void print_stats()
  604.    {
  605.    printf ("                  Statistics\n");
  606.    printf ("                  ----------\n\n");
  607.    printf ("# Rays:  %10ld    # Pixels:  %10ld  # Pixels supersampled: %10ld\n\n",
  608.             Number_Of_Rays, Number_Of_Pixels, Number_Of_Pixels_Supersampled);
  609.  
  610.    printf ("\nIntersection Tests:\n\n");
  611.    printf ("   Type       Tests    Succeeded\n");
  612.    printf ("   ----    ----------  ----------\n\n");
  613.    printf ("  Sphere   %10ld  %10ld\n", Ray_Sphere_Tests, Ray_Sphere_Tests_Succeeded);
  614.    printf ("  Plane    %10ld  %10ld\n", Ray_Plane_Tests, Ray_Plane_Tests_Succeeded);
  615.    printf ("  Triangle %10ld  %10ld\n", Ray_Triangle_Tests, Ray_Triangle_Tests_Succeeded);
  616.    printf ("  Quadric  %10ld  %10ld\n", Ray_Quadric_Tests, Ray_Quadric_Tests_Succeeded);
  617.    printf ("  Quartic  %10ld  %10ld\n", Ray_Quartic_Tests, Ray_Quartic_Tests_Succeeded);
  618.    printf ("  Bounds   %10ld  %10ld\n\n", Bounding_Region_Tests, Bounding_Region_Tests_Succeeded);
  619.    printf ("  Calls to Noise:   %10ld\n", Calls_To_Noise);
  620.    printf ("  Calls to DNoise:  %10ld\n", Calls_To_DNoise);
  621.    printf ("  Shadow Ray Tests: %10ld     Blocking Objects Found:  %10ld\n",
  622.               Shadow_Ray_Tests, Shadow_Rays_Succeeded);
  623.    printf ("  Reflected Rays:   %10ld\n", Reflected_Rays_Traced);
  624.    printf ("  Refracted Rays:   %10ld\n", Refracted_Rays_Traced);
  625.    printf ("  Transmitted Rays: %10ld\n", Transmitted_Rays_Traced);
  626.    }
  627.  
  628. /* Find a file in the search path. */
  629.  
  630. FILE *Locate_File (filename, mode)
  631.    char *filename, *mode;
  632.    {
  633.    FILE *f;
  634.    int i;
  635.    char pathname[FILE_NAME_LENGTH];
  636.  
  637.    /* Check the current directory first. */
  638.    if ((f = fopen (filename, mode)) != NULL)
  639.       return (f);
  640.  
  641.    for (i = 0 ; i < Library_Path_Index ; i++) {
  642.       strcpy (pathname, Library_Paths[i]);
  643.       if (FILENAME_SEPARATOR != NULL)
  644.          strcat (pathname, FILENAME_SEPARATOR);
  645.       strcat (pathname, filename);
  646.       if ((f = fopen (pathname, mode)) != NULL)
  647.          return (f);
  648.       }
  649.  
  650.    return (NULL);
  651.    }
  652.